package daytrader.data;

import java.io.*;
import java.util.*;
import daytrader.types.Sector;

public class DataModel implements DataAPI {
	private HashMap<String, ArrayList<TickData>> cache;
	private File dataRoot;
	public DataModel()
	{
		this.dataRoot = new File(".");
		this.cache = new HashMap<String, ArrayList<TickData>>();
	}
	public DataModel(String rootPath)
	{
		this.dataRoot = new File(rootPath);
		this.cache = new HashMap<String, ArrayList<TickData>>();
	}
	public String[] listStockNames()
	{
		/* This function will be re-written in the future */
		String[] stockNames = new String[5];
		stockNames[0] = "PG";
		stockNames[1] = "GOOG";
		stockNames[2] = "MSFT";
		stockNames[3] = "JPM";
		stockNames[4] = "KO";
		return stockNames;
	}
	public Sector getSector(String stockName)
	{
		if (stockName.equals("GOOG") || stockName.equals("MSFT")) {
			return Sector.Technology;
		} else if (stockName.equals("PG") || stockName.equals("KO")) {
			return Sector.Consumer;
		} else if (stockName.equals("JPM")) {
			return Sector.Financial;
		}
		return null;
	}
	private ArrayList<TickData> getTickDataList(String stockName)
	{
		if (cache.containsKey(stockName))
			return (ArrayList<TickData>)cache.get(stockName);
		String str;
		ArrayList<TickData> tickDataBuffer = new ArrayList<TickData>();
		try {
			BufferedReader in = new BufferedReader(
					new FileReader(
					new File(this.dataRoot, stockName + ".sto")));
			while ( (str = in.readLine()) != null ) {
				/* String tokenization */
				if (str.startsWith("%"))
					continue;
				ArrayList<String> tokensBuffer = new ArrayList<String>();
				StringTokenizer st = new StringTokenizer(str);
				while (st.hasMoreTokens()) {
					tokensBuffer.add(st.nextToken("\t"));
				}
				String[] strTokens = new String[tokensBuffer.size()];
				strTokens = tokensBuffer.toArray(strTokens);

				int tick = Integer.parseInt(strTokens[0]);
				double open = Double.parseDouble(strTokens[1]);
				double close = Double.parseDouble(strTokens[2]);
				double high = Double.parseDouble(strTokens[3]);
				double low = Double.parseDouble(strTokens[4]);
				int volumn = Integer.parseInt(strTokens[5]);
				tickDataBuffer.add(new TickData(tick, open, close, high, low, volumn));
			}
			in.close();
		} catch(IOException e) {
			e.printStackTrace();
		}
		cache.put(stockName, tickDataBuffer);
		return tickDataBuffer;
	}
	public TickData[] getTickData(String stockName)
	{
		ArrayList<TickData> dataList = getTickDataList(stockName);
		TickData[] data = new TickData[dataList.size()];
		return dataList.toArray(data);
	}
	public TickData[] getTickDataOfToday(String stockName)
	{
		ArrayList<TickData> dataList = getTickDataList(stockName);
		TickData[] data = new TickData[numberTicksPerDay];
		return dataList.subList(0, numberTicksPerDay).toArray(data);
	}
	public TickData[] getTickDataOfDate(String stockName, Date date)
	{
		Date todayBegin = stripTime( new Date() );
		Date dateBegin = stripTime( date );
		long diff = dateBegin.getTime() - todayBegin.getTime();
		return getTickDataByTimeDiff(stockName, diff);
	}
	private TickData[] getTickDataByTimeDiff(String stockName, long diff)
	{
		TickData[] data;
		if (diff > 0) {
			System.err.println("You are retrieving the future data: " + diff);
			data = new TickData[1];
			return data;
		}
		Long dayDiff = diff / (1000 * 60 * 60 * 24);
		
		ArrayList<TickData> dataList = getTickDataList(stockName);
		if (numberTicksPerDay * (Math.abs(dayDiff.intValue())+1) >= dataList.size()) {
			System.err.println("No such data. (the date is too old).");
			data = new TickData[1];
			return data;
		} else {
			data = new TickData[numberTicksPerDay];
			return dataList.subList(numberTicksPerDay * Math.abs(dayDiff.intValue()), 
				numberTicksPerDay * (Math.abs(dayDiff.intValue())+1)).toArray(data);
	
		}
	}
	public long getMarketActiveTimeDuration() {
		return this.marketActiveTime;
	}
	public long getMarketStartTimeOfToday() {
		Date todayBegin = stripTime( new Date() );
		return todayBegin.getTime() + this.marketStartTime;
	}
	public static void main (String [] args)
	{
		String[] stockNames;
		DataModel d = new DataModel("./src/daytrader/data/");
		Date today = new Date();
		long time = today.getTime() - (1000 * 60 * 60 * 24);
		stockNames = d.listStockNames();
		for (String s: stockNames) {
			TickData[] data = d.getTickDataOfDate(s, new Date(time));
			printTickData(data);
		}
	}
	private Date stripTime(Date date)
	{
		Calendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		Calendar dayBegin = new GregorianCalendar(
				calendar.get(Calendar.YEAR),
				calendar.get(Calendar.MONTH),
				calendar.get(Calendar.DAY_OF_MONTH));
		return dayBegin.getTime();
	}
	private static void printTickData(TickData[] data)
	{
		System.out.println("===================");
		for (TickData d : data) {
			System.out.print(d.tick);
			System.out.print("\t");
			System.out.print(d.open);
			System.out.print("\t");
			System.out.print(d.close);
			System.out.print("\t");
			System.out.print(d.high);
			System.out.print("\t");
			System.out.print(d.low);
			System.out.print("\t");
			System.out.print(d.volume);
			System.out.println();
		}
	}
}

